import routerMap, { view } from '@/router/async/router.map'
import { mergeI18nFromRoutes } from '@/utils/i18n'
import Router from 'vue-router'
import basicOptions from '@/router/basic'
import merge from 'lodash/merge'
// 根级菜单
const rootRouter = routerMap['root']

// 应用配置
const appOptions = {
  router: undefined,
  i18n: undefined,
  store: undefined
}

/**
 * 设置应用配置
 * @param options
 */
function setAppOptions(options) {
  const { router, store, i18n } = options
  appOptions.router = router
  appOptions.store = store
  appOptions.i18n = i18n
}
/**
 * 根据 路由配置 和 路由组件注册 解析路由
 * @param routesConfig 路由配置
 * @param routerMap 本地路由组件注册配置
 */
function parseRoutes(routesConfig, routerMap) {
  const routes = []
  routesConfig.forEach(item => {
    // 获取注册在 routerMap 中的 router，初始化 routeCfg
    let router; let routeCfg = {}
    if (typeof item === 'string') {
      router = routerMap[item]
      routeCfg = { path: (router && router.path) || item, router: item }
    } else if (typeof item === 'object') {
      router = routerMap[item.router]
      routeCfg = item
    }
    if (!router) {
      // console.warn(`can't find register for router ${routeCfg.router}, please register it in advance.`)
      router = typeof item === 'string' ? { path: item, name: item } : item
    }
    // 从 router 和 routeCfg 解析路由
    let meta = {
      icon: router.icon,
      // page: router.page,
      link: router.link,
      params: router.params,
      query: router.query,
      ...router.meta,
      key: router.key
    }
    const cfgMeta = {
      icon: routeCfg.icon,
      // page: routeCfg.page,
      link: routeCfg.link,
      params: routeCfg.params,
      query: routeCfg.query,
      ...routeCfg.meta
    }
    Object.keys(cfgMeta).forEach(key => {
      if (cfgMeta[key] === undefined || cfgMeta[key] === null || cfgMeta[key] === '') {
        delete cfgMeta[key]
      }
    })
    meta = Object.assign(meta, cfgMeta)

    let component = ''
    if (routeCfg.component && typeof routeCfg.component === 'function') {
      component = routeCfg.component
    } else if (routeCfg.component) {
      component = view[routeCfg.component] || (() => import(`@/pages/${routeCfg.component}.vue`))
    } else {
      component = router.component
    }
    const path = routeCfg.path || router.path || routeCfg.router
    let route
    // 处理嵌套iframe情况
    if (path.indexOf('http:') >= 0 || path.indexOf('https:') >= 0) {
      route = {
        path: router.key,
        name: routeCfg.name || router.name,
        component: view['iframePageView'],
        redirect: routeCfg.redirect || router.redirect,
        meta: { ...meta, link: path }, // hidden: meta.hidden invisible
        title: meta.title
      }
    } else {
      route = {
        path: path,
        name: routeCfg.name || router.name,
        component: component,
        redirect: routeCfg.redirect || router.redirect,
        meta: { ...meta }, // hidden: meta.hidden
        title: meta.title
      }
    }
    if (routeCfg.children && routeCfg.children.length > 0) {
      route.children = parseRoutes(routeCfg.children, routerMap)
    }
    routes.push(route)
  })
  return routes
}

/**
 * 加载路由
 * @param routesConfig {RouteConfig[]} 路由配置
 */
function loadRoutes(routesConfig) {
  // 应用配置
  const { router, store, i18n } = appOptions

  if (routesConfig && routesConfig.length > 0) {
    const menuNav = []
    rootRouter.children = routesConfig
    menuNav.push(rootRouter)
    const routes = parseRoutes(menuNav, routerMap) // 组装动态路由
    basicOptions.routes.push({ path: '*', redirect: '404' }) // 路由匹配不到，跳转404。
    const finalRoutes = deepMergeRoutes(basicOptions.routes, routes)// 合并静态路由
    router.options = { ...router.options, routes: finalRoutes }
    router.matcher = new Router({ ...router.options, routes: [] }).matcher
    router.addRoutes(finalRoutes)
  }

  // 提取路由国际化数据
  mergeI18nFromRoutes(i18n, router.options.routes)
  // 初始化Admin后台菜单数据
  const rootRoute = router.options.routes.find(item => item.path === '/')
  const menuRoutes = rootRoute && rootRoute.children
  if (menuRoutes) {
    store.commit('setting/setMenuData', menuRoutes)
  }
}

// /**
//  * 合并路由
//  * @param target {Route[]}
//  * @param source {Route[]}
//  * @returns {Route[]}
//  */
// function mergeRoutes(target, source) {
//   const routesMap = {}
//   target.forEach(item => routesMap[item.path] = item)
//   source.forEach(item => routesMap[item.path] = item)
//   return Object.values(routesMap)
// }

/**
 * 深度合并路由
 * @param target {Route[]}
 * @param source {Route[]}
 * @returns {Route[]}
 */
function deepMergeRoutes(target, source) {
  // 映射路由数组
  const mapRoutes = routes => {
    const routesMap = {}
    routes.forEach(item => {
      routesMap[item.path] = {
        ...item,
        children: item.children ? mapRoutes(item.children) : undefined
      }
    })
    return routesMap
  }
  const tarMap = mapRoutes(target)
  const srcMap = mapRoutes(source)

  // 合并路由
  const merge_ = merge(tarMap, srcMap)

  // 转换为 routes 数组
  const parseRoutesMap = routesMap => {
    return Object.values(routesMap).map(item => {
      if (item.children) {
        const children = parseRoutesMap(item.children)
        // 动态路由与静态路由合并之后，按order排序
        item.children = children.sort((pre, next) => {
          if (!pre.meta || pre.meta.order === '' || pre.meta.order === null || pre.meta.order === undefined) {
            return true
          }
          return pre.meta.order - next.meta.order
        })
        // item.children = parseRoutesMap(item.children)
      } else {
        delete item.children
      }
      return item
    })
  }
  return parseRoutesMap(merge_)
}

/**
 * 格式化路由
 * @param routes 路由配置
 */
function formatRoutes(routes) {
  routes.forEach(route => {
    const { path } = route
    if (!path.startsWith('/') && path !== '*') {
      route.path = '/' + path
    }
  })
}

/**
 * 从路由 path 解析 i18n key
 * @param path
 * @returns {*}
 */
function getI18nKey(path) {
  const keys = path.split('/').filter(item => !item.startsWith(':') && item != '')
  keys.push('name')
  return keys.join('.')
}

/**
 * 加载导航守卫
 * @param guards
 * @param options
 */
function loadGuards(guards, options) {
  const { beforeEach, afterEach } = guards
  const { router } = options
  beforeEach.forEach(guard => {
    if (guard && typeof guard === 'function') {
      router.beforeEach((to, from, next) => {
        return guard(to, from, next, options)
      })
    }
  })
  afterEach.forEach(guard => {
    if (guard && typeof guard === 'function') {
      router.afterEach((to, from) => guard(to, from, options))
    }
  })
}

export { parseRoutes, loadRoutes, getI18nKey, loadGuards, formatRoutes, setAppOptions, deepMergeRoutes }
